package com.libui.thirdpartsdk

import android.content.Intent
import android.util.Base64
import com.libbase.Weak
import com.libui.thirdpartsdk.login.Login
import com.libui.thirdpartsdk.openinstall.OpenInstallSDK
import com.libui.thirdpartsdk.share.ShareCompletion
import com.libui.thirdpartsdk.share.ShareInterface
import com.libui.thirdpartsdk.share.models.ShareImageObject
import com.libui.thirdpartsdk.share.models.ShareObjectInterface
import com.libui.thirdpartsdk.share.models.ShareObjectType
import com.libui.thirdpartsdk.share.models.ShareUrlObject
import com.libui.thirdpartsdk.systemsdk.SystemSDK

class SDKManager {
    interface Adapter {
        fun share(
            sdkManager: SDKManager, shareObject: Map<String, Any>, completion: ShareCompletion?
        )

        fun shareParams(completion: (shareParams: Map<String, String>?) -> Unit)
    }

    companion object {
        val instance by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            SDKManager()
        }
    }

    var defaultThumbImage: ByteArray? = null

    var adapter: Adapter? by Weak()

    private val sdkBuilders: MutableList<SDKInterface.Builder> = arrayListOf(
        SystemSDK.builder,
    )

    private val sdks: MutableList<SDKInterface> = mutableListOf()

    fun init() {
        register(OpenInstallSDK.builder, true)
    }

    fun register(sdkBuilder: SDKInterface.Builder, install: Boolean = false) {
        if (sdkBuilders.any { it.type == sdkBuilder.type }) {
            return
        }

        sdkBuilders.add(sdkBuilder)

        if (install) {
            val sdk = sdkBuilder.build()
            sdk.install()
            sdks.add(sdk)
        }
    }

    fun shareClasses(shareTypes: List<String>): List<ShareInterface.Builder> {
        return shareTypes.mapNotNull { shareType ->
            for (sdkBuilder in sdkBuilders) {
                val shareBuilder = sdkBuilder.shareBuilders?.firstOrNull {
                    it.type == shareType
                }

                if (shareBuilder != null) {
                    return@mapNotNull shareBuilder
                }
            }
            null
        }
    }

    fun sdk(type: String): SDKInterface? {
        var sdk: SDKInterface? = sdks.firstOrNull { it.type == type }

        if (sdk != null) {
            return sdk
        }

        sdk = sdkBuilders.firstOrNull { it.type == type }?.build()?.apply {
            install()
            sdks.add(this)
        }

        return sdk
    }

    fun shareInstance(type: String): ShareInterface? {
        return sdkBuilders.firstOrNull { it.shareBuilders?.any { shareBuilder -> shareBuilder.type == type } == true }
            ?.let {
                sdk(it.type)?.let { sdk ->
                    sdk.shareBuilders?.firstOrNull { shareBuilder -> shareBuilder.type == type }
                        ?.build(sdk)
                }
            }
    }

    fun loginInstance(type: String): Login? {
        return sdkBuilders.firstOrNull { it.loginBuilder?.type == type }?.let {
            sdk(it.type)?.let { sdk ->
                sdk.loginBuilder?.build(sdk)
            }
        }
    }

    fun handleIntent(intent: Intent): Boolean {
        var result = false

        for (sdk in sdks) {
            if (sdk.handleIntent(intent)) {
                result = true
                break
            }
        }

        return result
    }

    private fun createShareObject(values: Map<String, Any>): ShareObjectInterface? {
        return (values["type"] as? String)?.let { type ->
            when (ShareObjectType.allTypes[type]) {
                ShareObjectType.URL -> {
                    (values["url"] as? String)?.let { url ->
                        ShareUrlObject(
                            title = values["title"] as? String,
                            description = values["description"] as? String,
                            url = url,
                        )
                    }
                }

                ShareObjectType.IMAGE -> {
                    (values["imageData"] as? String)?.let { imageDataBase64 ->
                        Base64.decode(imageDataBase64, Base64.DEFAULT)?.let { imageData ->
                            ShareImageObject(
                                title = values["title"] as? String ?: "",
                                description = values["description"] as? String,
                                thumbImage = values["thumbImage"] as? ByteArray,
                                imageData = imageData,
                            )
                        }
                    }
                }
                else -> null
            }
        }
    }

    fun share(shareObject: Map<String, Any>, completion: ShareCompletion?) {
        adapter?.share(this, shareObject, completion)
    }

    fun share(shareObject: ShareObjectInterface, completion: ShareCompletion?) {
        share(shareObject.toJson(), completion)
    }

    fun share(type: String, shareObject: Map<String, Any>, completion: ShareCompletion?) {
        createShareObject(shareObject)?.let {
            share(type, it, completion)
        } ?: run {
            completion?.let { false }
        }
    }

    fun share(type: String, shareObject: ShareObjectInterface, completion: ShareCompletion?) {
        shareInstance(type)?.let { share ->
            share.share(shareObject, completion)
        } ?: run {
            completion?.let { it(false) }
        }
    }
}